const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');
const Ajv = require('ajv');
const localize = require("ajv-i18n");

const ajv = new Ajv({ allErrors: true });
require('ajv-errors')(ajv);
require('ajv-formats')(ajv);

const app = new Koa();
const router = new Router();

// 定义 JSON Schema
const schema = {
    type: 'object',
    properties: {
        // 姓名，长度在3到20之间
        name: { type: 'string', minLength: 3, maxLength: 20, description: '姓名，长度在3到20之间' },

        // 年龄，必须是整数且不小于18
        age: { type: 'integer', minimum: 18, description: '年龄，必须是整数且不小于18' },

        //余额,可以是浮点数
        balance: {
            type: "number",
            not: { type: "null" }
        },

        // 爱好，是一个字符串数组
        hobbies: {
            type: 'array',
            items: { type: 'string' },
            description: '爱好，是一个字符串数组',
        },

        // 电子邮箱，必须符合邮箱格式
        email: { type: 'string', format: 'email', description: '电子邮箱，必须符合邮箱格式' },

        // 生日，必须符合日期格式
        birthday: { type: 'string', format: 'date', description: '生日，必须符合日期格式' },

        // 值，是一个包含数字和字符串的数组，且不能超过两个元素
        values: {
            type: 'array',
            not: { type: 'null' },
            items: [
                { type: 'integer', description: '第一个值是数字' },
                { type: 'string', description: '第二个值是字符串' },
            ],
            additionalItems: false, // 防止数组包含超过两个元素
            description: '值，是一个包含数字和字符串的数组，且不能超过两个元素',
        },
        colors:{
            type: 'string',
            enum: ['red', 'green', 'blue'],
        },
        // 地址列表，是一个包含城市和邮政编码的对象数组
        addresses: {
            type: 'array',
            items: {
                type: 'object',
                properties: {
                    // 城市
                    city: { type: 'string', description: '城市' },

                    // 邮政编码
                    zipCode: { type: 'string', description: '邮政编码' },
                },
                required: ['city', 'zipCode'],
            },
            description: '地址列表，是一个包含城市和邮政编码的对象数组',
        },
        //是否软删除 应当是 null 类型
        isDelete: {
            type: "null",
        }
    },
    required: ['name', 'age', 'values', 'addresses', 'birthday', 'email', 'card','colors'],
};
// 中间件：校验请求数据
const validateMiddleware = async (ctx, next) => {
    const data = ctx.request.body;

    // 编译 JSON Schema
    const validate = ajv.compile(schema);

    // 验证数据是否符合 JSON Schema
    const isValid = validate(data);

    if (!isValid) {
        // 指定语言为中文
        localize.zh(validate.errors);
        // 设置 errorsText 选项为中文
        const errorText = ajv.errorsText(validate.errors, { separator: '\n', dataVar: 'data' });

        ctx.status = 400;
        ctx.body = {
            error: 'Invalid data',
            details:errorText,
        };
        return;
    }

    await next();
};

// 使用中间件
app.use(bodyParser());

// 路由处理
router.post('/api/data', validateMiddleware, async (ctx) => {
    ctx.body = { message: '数据验证通过' };
});

// 添加路由
app.use(router.routes());
app.use(router.allowedMethods());

// 启动应用
const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});
